package com.atguigu.gulimall.order.service.impl;

import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.common.vo.MemberResponseVo;
import com.atguigu.gulimall.order.dao.OrderDao;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.atguigu.gulimall.order.feign.CartFeignService;
import com.atguigu.gulimall.order.feign.MemberFeignService;
import com.atguigu.gulimall.order.interceptor.LoginUserInterceptor;
import com.atguigu.gulimall.order.service.OrderService;
import com.atguigu.gulimall.order.vo.MemberAddressVo;
import com.atguigu.gulimall.order.vo.OrderConfirmVo;
import com.atguigu.gulimall.order.vo.OrderItemVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private MemberFeignService memberFeignService;
    @Autowired
    private CartFeignService cartFeignService;
    @Autowired
    private ThreadPoolExecutor executor;    // 线程池（给线程池中提交异步任务）

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );
        return new PageUtils(page);
    }

    /**
     * 订单确认页返回需要用的数据
     */
    @Override
    public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
        OrderConfirmVo confirmVo = new OrderConfirmVo();
        // 获取当前用户登录的信息
        MemberResponseVo responseVo = LoginUserInterceptor.loginUser.get();

        // 获取主线程中原来的请求数据
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        // 采用异步任务的方式进行远程查询
        CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
            // 当前线程共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            // 1、远程查询所有的收获地址列表
            List<MemberAddressVo> address = memberFeignService.getAddress(responseVo.getId());
            confirmVo.setAddress(address);
        }, executor);

        CompletableFuture<Void> cartItemFuture = CompletableFuture.runAsync(() -> {
            // 每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            /** 重点：【Feign远程调用丢失请求头问题】远程服务发请求，带上之前老请求的请求头cookie信息 */
            // 2、远程查询购物车所有选中的购物项
            List<OrderItemVo> cartItems = cartFeignService.getCurrentUserCartItems();
            confirmVo.setItems(cartItems);
        }, executor);

        // 3、查询用户积分
        Integer integration = responseVo.getIntegration();
        confirmVo.setIntegration(integration);

        // 4、其他数据自动计算（订单总额、应付价格）

        // todo 5、防重令牌（幂等性）


        CompletableFuture.allOf(addressFuture, cartItemFuture).get();
        return confirmVo;
    }

}